﻿/*!	@file	r_gui_widget.h
	@brief	GUI
Copyright (c) 2010 Yuya Yamaguchi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _R_DEBUG_WIDGET_H_
#define _R_DEBUG_WIDGET_H_

#include "../rtti/r_rtti_class_base.h"
#include "../util/r_util_stdstring.h"
#include "r_gui_def.h"
#include "r_gui_allocator.h"
#include "r_gui_string.h"
#include <vector>

namespace r{
	namespace gui{
		class Widget;
		typedef	std::vector< Widget*, Allocator<Widget*> >	Widget_array;

		class Event;

		namespace draw{
			class Draw;
		}
	}
}

namespace r{
	namespace gui{

		//! GUIウィジェット
		/*! ウィジェットから派生するクラスはdeleteでの削除を禁止します。
		*/
		class Widget : public r::rtti::ClassBase
		{
			RRTTI_REFLECTION_DECLARE
			friend class Server;
		public:
			RALLOC_PLACEMENT_NEW_DELETE_DECLEARE
			//! コンストラクタ
			/*!
			*/
			Widget();
			//! デストラクタ
			/*!
			*/
			virtual	~Widget();
		public:
			// システム呼び出し
			//! 更新処理
			/*! 基本的にオーバーライドの必要はないはずですが、
			過去の経験から一応オーバーライド可能にします。
			*/
			virtual	void				update ( Event& guiEvent );
			virtual	void				updateCkickInRectLMB ( Event& guiEvent );
			virtual	void				updateDoubleCkickInRectLMB ( Event& guiEvent );
			virtual	void				updateReleaseInRectLMB ( Event& guiEvent );
			virtual	void				updateReleaseOutRectLMB ( Event& guiEvent );
			virtual	void				updateDragLMB ( Event& guiEvent );
			virtual	void				updateDragHoverInRectLMB ( Event& guiEvent );
			virtual	void				updateDragReleaseInRectLMB ( Event& guiEvent );
			virtual void				updateHoverInRect ( Event& guiEvent );

			virtual	void				begin ( Event& guiEvent );
			//! 位置座標が矩形内にあるか判定する
			/*!
			*/
			virtual	r_bool				checkInRect ( r_ui32 x, r_ui32 y ) const;
			//! 描画処理
			/*! 基本的にオーバーライドの必要はないはずですが、
			過去の経験から一応オーバーライド可能にします。
			*/
			virtual	void				draw ( draw::Draw& guidraw );

			//! 削除時のキーボードフォーカスの破棄等
			virtual	void				destroy ( Event& guiEvent );
		protected:
			// ユーザインターフェース
			//! 更新
			/*! これが実際に呼び出される更新処理です。
			各GUIはこの関数をオーバーライドして独自の更新処理を実装してください。

			@param	event	[io]	サーバから作成されたイベント情報です、このイベントを元に各GUIは更新処理を記述してください。
			*/
			virtual	void				onUpdate ( Event& guiEvent );
			//! 描画処理
			/*! これが実際に呼び出される描画処理です。
			各GUIはこの関数をオーバーライドして独自の更新処理を実装してください。
			*/
			virtual	void				onDraw ( draw::Draw& guidraw );
			//! 矩形内でクリックされた場合に呼び出される関数
			/*!
			*/
			virtual	void				onClickInRectLMB ( Event& guiEvent );
			//! 矩形内でダブルクリックされた場合に呼び出される関数
			/*!
			*/
			virtual void				onDoubleClickInRectLMB ( Event& guiEvent );
			//! 矩形内でリリースされた場合に呼び出される関数
			/*!
			*/
			virtual void				onReleaseInRectLMB ( Event& guiEvent );
			//! 矩形外でリリースされた場合に呼び出される関数
			/*!
			*/
			virtual void				onReleaseOutRectLMB ( Event& guiEvent );
			//! ドラッグ中に呼び出される関数
			/*!
			*/
			virtual void				onDragLMB ( Event& guiEvent );
			//! ドラッグオブジェクトを持った状態で矩形内に侵入している時に呼び出される関数
			/*!
			*/
			virtual	void				onDragHoverInRectLMB ( Event& guiEvent );
			//! ドラッグオブジェクトを矩形内でリリースした際に呼び出される関数
			/*!
			*/
			virtual	void				onDragReleaseInRectLMB ( Event& guiEvent );
			//! マウスカーソルが矩形内にある時に呼び出される関数
			/*!
			*/
			virtual	void				onHoverInRect ( Event& guiEvent );
			//! キーボードフォーカスを得た時に呼び出される関数
			/*!
			*/
			virtual	void				onGetKeyboardFocus ( Event& guiEvent );
			//! キーボードフォーカスを失った時に呼び出される関数
			/*!
			*/
			virtual	void				onLostKeyboardFocus ( Event& guiEvent );
			//! キーボードフォーカス中に呼び出される関数
			/*!
			*/
			virtual	void				onUpdateKeyboardFocus ( Event& guiEvent );
		public:
			//! 位置の取得
			/*!
			*/
			virtual void				getPos ( r_ui32& x, r_ui32& y ) const;
			//! 幅の取得
			/*!
			*/
			virtual void				getSize ( r_ui32& w, r_ui32& h ) const;
			//! 位置の設定
			/*!
			*/
			virtual	void				setPos ( r_ui32 x, r_ui32 y );
			//! 幅の設定
			/*!
			*/
			virtual	void				setSize ( r_ui32 w, r_ui32 h );

			//! 名前を設定する
			virtual void				setName ( const r_cstr text );
			//! 名前を取得する
			virtual const r_cstr		getName() const;
			virtual r_size				getNameLength() const;

			//! 表示非表示
			/*!
			*/
			virtual	void				setVisible ( r_si32 mode );
			///
			/*!
			*/
			virtual	r_si32				getVisible() const;

			//! ホバーチェック
			virtual	r_bool				getIsHover() const;
		public:
			//! 自動配置設定
			/*! トップにあるGUIはこのフラグを無視する
			@param	laytou	[in]	eRGUIAutoLayout
			*/
			virtual	void				setAutoLaytou ( r_ui32 layout );
			//! 子GUIを追加する
			/*!
			*/
			virtual	void				addChild ( Widget* widget );
			//! 親を参照
			/*!
			*/
			Widget*				getParent() const;
			//! 子の要素数を取得
			/*!
			*/
			r_size						getChildNum() const;
			//! 子を参照
			/*!
			*/
			Widget*				getChild ( r_size index ) const;
		protected:
			//! 最小矩形サイズ
			r_si32						minWidth;
			r_si32						minHeight;
			//! 位置
			r_si32						posX;
			r_si32						posY;
			r_si32						posW;
			r_si32						posH;
			r_si32						posOffL;
			r_si32						posOffR;
			r_si32						posOffT;
			r_si32						posOffB;
			//! ワールド位置
			r_si32						wposX;
			r_si32						wposY;
			//! 自動配置フラグ
			r_ui32						widgetAutoLayout;
			//! ホバーか否か
			r_bool						isHover;
		private:
			// システム呼び出し
			//! 削除の為に親子関係を調整する
			/*!
			*/
			void						remove();
			//! ワールドの位置座標更新
			/*!
			*/
			virtual	void				updateWorldPosition ( r_ui32 wx, r_ui32 wy );
		private:
			//! GUI widgetの名前
			r::gui::string				name;
			//! 可視/不可視	eRGUIVisible
			r_ui32						visible;
			//! 親ノード
			Widget*				parent;
			//! 子ノード
			Widget_array			child;
		};
	}
}


#endif // _R_DEBUG_WIDGET_H_
